/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Traffic;

import java.util.Vector;

/**
 *
 * @author Matthew
 */
public class TrafficLightController {
    //The states that this intersection cycles through.
    private Vector<TrafficSignal> signals;
    //The traffic lights
    TrafficLight north, south, east, west, northEast, southWest, eastSouth, westNorth;
    //Array for cycling through all the traffic lights
    TrafficLight[] lights;
    //The time remaining for the current state
    private int timeRemaining;
    //The current signal in use
    private int singleIndex;
    //The state of the lights in the intersection
    private LightState curState;
    //The current state of each light
    private LightState[] curStates;


    //Constructor sets up a basic set of signals with the provided times
    TrafficLightController(Zones zones)
    {
        //Initialise the TrafficLight Array
        lights = new TrafficLight[8];
        curStates = new LightState[8];


        //Initialise the TrafficLights

        //North
        //Initialise the zone for the traffic light
        PositionArea p = new PositionArea(Settings.LANE_LENGTH,
                Settings.LANE_LENGTH + (Settings.eastLanes + Settings.westLanes + 1) * Settings.LANE_WIDTH + 1,
                Settings.northLanes * Settings.LANE_WIDTH, 1);
        Zone z = new Zone(p, ZoneType.BLOCKAGE);
        //Add it to the zones object
        zones.addZone(z);
        //Initialise the Traffic Light
        north = lights[0] = new TrafficLight(z);

        //South
        p = new PositionArea(Settings.LANE_LENGTH + (Settings.northLanes + 1) * Settings.LANE_WIDTH,
                Settings.LANE_LENGTH - 2, Settings.southLanes * Settings.LANE_WIDTH, 1);
        z = new Zone(p, ZoneType.BLOCKAGE);
        zones.addZone(z);
        south = lights[1] = new TrafficLight(z);

        //East
        p = new PositionArea(Settings.LANE_LENGTH - 2, Settings.LANE_LENGTH,
                1, Settings.LANE_WIDTH * Settings.eastLanes);
        z = new Zone(p, ZoneType.BLOCKAGE);
        zones.addZone(z);
        east = lights[2] = new TrafficLight(z);

        //West
        p = new PositionArea(Settings.LANE_LENGTH + (Settings.northLanes + Settings.southLanes + 1) * Settings.LANE_WIDTH + 1,
                Settings.LANE_LENGTH + (Settings.eastLanes + 1) * Settings.LANE_WIDTH, 1, Settings.LANE_WIDTH * Settings.westLanes);
        z = new Zone(p, ZoneType.BLOCKAGE);
        zones.addZone(z);
        west = lights[3] = new TrafficLight(z);

        //Northbound turning lane
        p = new PositionArea(Settings.LANE_LENGTH + Settings.northLanes * Settings.LANE_WIDTH,
                Settings.LANE_LENGTH + (Settings.eastLanes + Settings.westLanes + 1) * Settings.LANE_WIDTH + 1,
                Settings.LANE_WIDTH, 1);
        z = new Zone(p, ZoneType.BLOCKAGE);
        zones.addZone(z);
        northEast = lights[4] = new TrafficLight(z);

        //Southbound Turning
        p = new PositionArea(Settings.LANE_LENGTH + Settings.northLanes * Settings.LANE_WIDTH,
                Settings.LANE_LENGTH - 2, Settings.LANE_WIDTH, 1);
        z = new Zone(p, ZoneType.BLOCKAGE);
        zones.addZone(z);
        southWest = lights[5] = new TrafficLight(z);

        //Eastbound Turning
        p = new PositionArea(Settings.LANE_LENGTH - 2, Settings.LANE_LENGTH + Settings.eastLanes * Settings.LANE_WIDTH,
                1, Settings.LANE_WIDTH);
        z = new Zone(p, ZoneType.BLOCKAGE);
        zones.addZone(z);
        eastSouth = lights[6] = new TrafficLight(z);

        //West Turning
        p = new PositionArea(Settings.LANE_LENGTH + (Settings.northLanes + Settings.southLanes + 1) * Settings.LANE_WIDTH + 1,
                Settings.LANE_LENGTH + Settings.eastLanes * Settings.LANE_WIDTH, 1, Settings.LANE_WIDTH);
        z = new Zone(p, ZoneType.BLOCKAGE);
        zones.addZone(z);
        westNorth = lights[7] = new TrafficLight(z);

        //Initialise the vector of signals
        signals = new Vector();
        //Add signal for north and south through traffic
        signals.add(new TrafficSignal(LightState.GREEN, LightState.GREEN, LightState.RED, LightState.RED,
                LightState.RED, LightState.RED, LightState.RED, LightState.RED, Settings.timeNS));
        //Add signal for east and west through traffic
        signals.add(new TrafficSignal(LightState.RED, LightState.RED, LightState.GREEN, LightState.GREEN,
                LightState.RED, LightState.RED, LightState.RED, LightState.RED, Settings.timeEW));
        //Add signal for north and south turning traffic
        signals.add(new TrafficSignal(LightState.RED, LightState.RED, LightState.RED, LightState.RED,
                LightState.GREEN, LightState.GREEN, LightState.RED, LightState.RED, Settings.timeNSTurn));
        //Add signal for east and west turning traffic
        signals.add(new TrafficSignal(LightState.RED, LightState.RED, LightState.RED, LightState.RED,
                LightState.RED, LightState.RED, LightState.GREEN, LightState.GREEN, Settings.timeEWTurn));

        //Set the Traffic Lights to their initial state
        singleIndex = 0;
        curState = LightState.RED;
        loadCycle(0);

        //Get the initial state for the view
        for (int i = 0; i < 8; ++i)
        {
            //Copy its value to the array to return
            curStates[i] = lights[i].getState();
        }
    }

    //Gets the state of each TrafficLight
    public LightState[] getLightStates()
    {
        //Return the lightstate array
        return curStates;
    }

    //Tells the controller that 0.2 of a second has passed
    public void tick()
    {
        //If this cycle has time left
        if (timeRemaining > 0)
        {
            //Remove some time
            timeRemaining -= 1;
        }
        //If time to change
        else
        {
            //Cycle the intersection's state
            cycleState();
        }

    }

    //Cycles the intersection to the next signal
    private void cycleState()
    {
        //If there are green lights
        if (curState == LightState.GREEN)
        {
            //We change to yellow
            curState = LightState.YELLOW;

            //Change the green lights to yellow
            for (TrafficLight t:lights)
            {
                if (t.getState() == LightState.GREEN)
                {
                    t.setState(curState);
                }
            }

            //Set time for lights to remain yellow
            timeRemaining = Settings.YELLOW_LENGTH;
        }
        else if(curState == LightState.YELLOW)
        {
            //We change to red
            curState = LightState.RED;

            //We change all lights to red
            for (TrafficLight t:lights)
            {
                t.setState(LightState.RED);
            }

            //Wait for intersection to clear
            timeRemaining = Settings.RED_LENGTH;

        }
        //If the intersection is completely red
        else
        {
            //Load the next signal
            loadCycle(++singleIndex);
        }

        //Keep the curstates up to date for the view
        //For each light
        for (int i = 0; i < 8; ++i)
        {
            //Copy its value to the array to return
            curStates[i] = lights[i].getState();
        }

    }

    private void loadCycle(int signal)
    {
        signal = signal % signals.size();
        //Get the signal to load
        TrafficSignal curSingle = signals.get(signal);

        //Load the state into each light
        north.setState(curSingle.north);
        south.setState(curSingle.south);
        east.setState(curSingle.east);
        west.setState(curSingle.west);
        northEast.setState(curSingle.northEast);
        southWest.setState(curSingle.southWest);
        eastSouth.setState(curSingle.eastSouth);
        westNorth.setState(curSingle.westNorth);

        //Set the duration to stay in this state
        timeRemaining = curSingle.duration;

        curState = LightState.GREEN;
    }


}
